<?php

namespace app\sys\service;

use think\admin\Exception;
use think\admin\Library;
use think\admin\service\AlipayService;
use think\admin\service\AdminService;
use think\admin\extend\JwtExtend;
use think\admin\service\WechatService;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Exceptions\LocalCacheException;
use WeMini\Qrcode;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Writer\PngWriter;
use \Endroid\QrCode\Encoding\Encoding;
/**
 * 扫码登录服务
 * @class LoginService
 * @package app\auth\service
 */
class LoginService
{
    private const expire = 3600;
    private const prefix = 'thirdLogin';

    /**
     * 生成请求编号
     * @return string
     */
    public static function gcode(): string
    {
        return md5(uniqid(strval(rand(0, 10000)), true));
    }

    /**
     * 获取微信小程序配置
     * @return array
     * @throws Exception
     */
    public static function getWechatConfig(): array
    {
        return [
            'appid' => sysconfig('WECHAT_MINI', 'SQM_WECHAT_WXAPP_APPID'),
            'appsecret' => sysconfig('WECHAT_MINI', 'SQM_WECHAT_WXAPP_APPKEY'),
            'cache_path' => Library::$sapp->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'wechat'
        ];
    }

    /**
     * 生成授权二维码
     * @param string $type
     * @param string $path
     * @param string $code
     * @return array
     * @throws Exception
     * @throws InvalidResponseException
     * @throws LocalCacheException
     */
    public static function qrcode(string $type, string $path, string $code): array
    {
        $data = ['auth' => self::gauth($code)];
        if ($type === 'ALIPAY') {
            $qrcode = AlipayService::instance()->crtQrcode($path, 'code=' . $code);
        } elseif($type === 'WECHAT') {
            $result = Qrcode::instance([
                'appid' => sysconfig('WECHAT_MINI', 'SQM_WECHAT_WXAPP_APPID'),
                'appsecret' => sysconfig('WECHAT_MINI', 'SQM_WECHAT_WXAPP_APPKEY'),
                'cache_path' => Library::$sapp->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'wechat'
            ])->createMiniScene($code, $path, 200);
            $qrcode = 'data:image/png;base64,' . base64_encode($result);
        } else {
            //$text = url('sys/third/getAuth', [], false, true) . "?code={$code}";
            $qrcode = self::crtQrCode($code);
        }
        Library::$sapp->cache->set('code', $code, self::expire);
        return ['code' => $code, 'image' => $qrcode]; // 'auth' => $data['auth'],
    }

    /**
     * 生成授权码
     * @param string $code 请求编号
     * @return string
     */
    public static function gauth(string $code): string
    {
        return self::prefix . md5($code);
    }

    /**
     * 发起授权处理
     * @param string $auth 授权编号
     * @param int $mode
     * @return bool
     * @return bool
     * @throws Exception
     * @throws InvalidResponseException
     * @throws LocalCacheException
     */
    public static function oauth(string $auth = '', int $mode = 0): bool
    {
        if (stripos($auth, self::prefix) === 0) {
            $url = Library::$sapp->request->url(true);
            $fans = WechatService::getWebOauthInfo($url, $mode);
            if (isset($fans['openid'])) {
                Library::$sapp->cache->set($auth, $fans, self::expire);
                return true;
            }
        }
        return false;
    }

    /**
     * 检查是否授权
     * @param string $code 请求编号
     * @return ?array
     */
    public static function query(string $code): ?array
    {
        $result = Library::$sapp->cache->get(self::gauth($code));
        if(isset($result) && $result['scanStatus']===2){
            self::remove($code);
        }
        return $result;
    }

    /**
     * 删除授权缓存
     * @param string $code
     * @return bool
     */
    public static function remove(string $code): bool
    {
        return Library::$sapp->cache->delete(self::gauth($code));
    }

    /**
     * app扫码
     * @param string $auth 授权编号
     * @return bool
     */
    public static function oauthScan(string $auth = ''): bool
    {
        if (stripos($auth, self::prefix) === 0) {
            Library::$sapp->cache->set($auth, ['scanStatus' => 1], self::expire);
            return true;
        }
        return false;
    }
    /**
     * app确认授权处理
     * @param string $auth 授权编号
     * @return bool
     */
    public static function oauthApp(string $auth = ''): bool
    {
        if (stripos($auth, self::prefix) === 0) {
            $user = AdminService::getUser();
            if ($user['id'] > 0) {
                $payload['data'] = ['id' => $user['id'], 'account' => $user['account']];
                $arr = JwtExtend::authorizations($payload);
                $arr['scanStatus'] = 2;
                Library::$sapp->cache->set($auth, $arr, self::expire);
                return true;
            }
        }
        return false;
    }

    /**
     * 生成APP扫码二维码
     * @param string $text
     * @return string
     */
    public static function crtQrCode(string $text): string
    {
        $result = Builder::create()
            ->writer(new PngWriter())
            ->writerOptions([])
            ->data($text)
            ->encoding(new Encoding('UTF-8'))
            ->size(300)
            ->margin(10)
            ->validateResult(false)
            ->build();
        return $result->getDataUri();
    }
}